home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1998 #4 / Amiga Plus CD - 1998 - No. 4.iso / pd / tools / wbstars2.0 / source / cback.a next >
Text File  |  1997-05-25  |  14KB  |  536 lines

  1. *
  2. * C initial startup procedure under AmigaDOS
  3.  
  4.         INCLUDE "exec/types.i"
  5.         INCLUDE "exec/alerts.i"
  6.         INCLUDE "exec/nodes.i"
  7.         INCLUDE "exec/lists.i"
  8.         INCLUDE "exec/ports.i"
  9.         INCLUDE "exec/libraries.i"
  10.         INCLUDE "exec/tasks.i"
  11.         INCLUDE "exec/memory.i"
  12.         INCLUDE "exec/execbase.i"
  13.         INCLUDE "libraries/dos.i"
  14.         INCLUDE "libraries/dosextens.i"
  15. FUNCDEF         MACRO   * function
  16. _LVO\1          EQU     FUNC_CNT
  17. FUNC_CNT        SET     FUNC_CNT-6
  18.                 ENDM
  19.  
  20. FUNC_CNT        SET     LIB_NONSTD
  21.  
  22.         INCLUDE "exec/exec_lib.i"
  23.         INCLUDE "libraries/dos_lib.i"
  24.         INCLUDE "workbench/startup.i"
  25.  
  26. AbsExecBase EQU 4
  27.  
  28. TINY    EQU     0
  29. callsys macro
  30.         CALLLIB _LVO\1
  31.         endm
  32.         
  33.     xdef    XCEXIT            ; exit(code) is standard way to leave C.
  34.     xdef     @XCEXIT
  35.     
  36.     xref    LinkerDB        ; linker defined base value
  37.     xref    _BSSBAS        ; linker defined base of BSS
  38.     xref    _BSSLEN        ; linker defined length of BSS
  39.  
  40.     xref    _main            ; Name of C program to start with.
  41.         xref    __fpinit                * initialize floating point
  42.         xref    __fpterm                * terminate floating point
  43.  
  44. *    library references
  45.  
  46.     csect    _NOMERGE,0,0,0,4
  47.     xref    MemCleanup
  48.     xref    FindTask
  49.  
  50. start:
  51.         movem.l d1-d6/a0-a6,-(a7)
  52. REGSIZE EQU     (6+7)*4
  53.         lea     REGSIZE(a7),A5         * determine old stack pointer
  54.         move.l  a0,a2                  * save command pointer
  55.         move.l  d0,d2                  * and command length
  56.         lea     LinkerDB,a4            * load base register
  57.  
  58.         move.l  AbsExecBase.W,a6
  59.         move.l  a6,SysBase(A4)
  60.         move.l  a7,_StackPtr(A4)       * Save stack ptr
  61.         clr.l   WBenchMsg(A4)
  62.  
  63. *------    Clear out our BSS section
  64.         lea     _BSSBAS,a3             * get base of BSS
  65.         moveq   #0,d1
  66.         move.l  #_BSSLEN,d0            * get length of BSS in longwords
  67.         bra.s   clr_lp                 * and clear for length given
  68. clr_bss move.l  d1,(a3)+
  69. clr_lp  dbf     d0,clr_bss
  70.  
  71. *------ get the address of our task
  72.     move.l    ThisTask(a6),A3
  73.  
  74. *-----  clear any pending signals
  75.     moveq    #0,d0
  76.     move.l    #$00003000,d1
  77.     callsys    SetSignal
  78.  
  79. *------ are we running as a son of Workbench?
  80.     move.l    pr_CurrentDir(A3),curdir(A4)
  81.     tst.l    pr_CLI(A3)
  82.     beq    fromWorkbench
  83.  
  84. *=======================================================================
  85. *====== CLI Startup Code ===============================================
  86. *=======================================================================
  87.  
  88. fromCLI:
  89. *------    attempt to open DOS library:
  90.     bsr.w    openDOS
  91.  
  92. *------ Duplicate the current directory for the called process
  93.     move.l    curdir(A4),D1
  94.     move.l    DOSBase(A4),A6
  95.         callsys DupLock
  96.         move.l  D0,curdir(A4)
  97.  
  98. *------ find command name:
  99.     move.l    pr_CLI(A3),a0
  100.     add.l   a0,a0            ; bcpl pointer conversion
  101.     add.l   a0,a0
  102.     move.l    cli_CommandName(a0),a1
  103.     add.l   a1,a1            ; bcpl pointer conversion
  104.     add.l   a1,a1
  105.  
  106. *------    collect parameters:
  107.     move.l    d2,d0        ; get command line length
  108.     moveq.l    #0,d1
  109.     move.b    (a1)+,d1
  110.         move.l  A1,D4                   ;save our pointer
  111.     move.l    d1,d3
  112.     add.l    d1,d1            ; double length since we copy it twice
  113.     add.l    d1,d0            ; add length of command name
  114.     addq.l    #5,d0            ; allow for space after command    
  115.     addq.l    #4,d0            ; As well as for the roundup
  116. *                          ; changed from 5 to 9 for quotes
  117. *                                         
  118. *------    We have the length of the command string to be copied.
  119. *------    Allocate space for it.
  120. *------    Round up to the nearest 4 bytes
  121.     lsl.l    #2,d0
  122.     add.l    memsize(A4),d0
  123.     move.l    d0,memsize(A4)
  124.  
  125. ************************************************************************
  126. ************************************************************************
  127. ******** Allocate and copy over the code to do the magic stuff *********
  128. ************************************************************************
  129. ************************************************************************
  130.  
  131.     lea    memlist(A4),A0
  132.         move.l  AbsExecBase.W,a6
  133.     callsys    AllocEntry        ;get a place to put the code
  134. *    btst.l    #31,d0            ;did we get the memory we asked for?
  135. *    beq    cliexit            ;no, can't do anything then
  136.     move.l    D0,A1
  137.     move.l    D0,-(A7)        ;remember the chunk we allocated
  138.  
  139. *------ Now we copy the code over
  140.     movea.l    ML_SIZE+ME_ADDR(A1),A1    ;locate our allocated block
  141.  
  142. *------    Copy over the command line to the allocated area
  143.     lea    commandbuf-copybeg(A1),A3
  144.  
  145. *------    At this point, we have:
  146. *        A0 - Work pointer
  147. *        A1 - Pointer to Allocated memory block
  148. *        A2 - Pointer to program name
  149. *        A3 - Pointer to target buffer
  150. *        A3 - Pointer to our process structure
  151. *        D0 - Work register
  152. *        D1 - Work register
  153. *        D2 - length of command name
  154. *        D3 - length of program name
  155. *               D4 - Pointer to program name
  156.  
  157.     movea.l    D4,A0            ; Load program name
  158.     move.l    D3,D0            ;      and length
  159.         move.b  #'"',(a3)+
  160.     bra.s    cpy1
  161. cpycmd:    move.b    (A0)+,(A3)+        ; copy over the command name
  162. cpy1:    dbf    d0,cpycmd
  163.         move.b  #'"',(a3)+
  164.     move.b    #' ',(A3)+        ; add the space delimiter
  165.  
  166.     move.l    A2,A0            ; Load command text
  167.     move.l    D2,D0            ;      and length
  168.     bra.s    cpy2
  169. cpylin:    move.b    (A0)+,(A3)+
  170. cpy2:    dbf    d0,cpylin
  171.     clr.b    (A3)+
  172.  
  173. *------    Now copy over the program name
  174.     move.l    A3,_ProgramName(A4)
  175.     move.l    D4,A0
  176.     move.l    D3,D0
  177.     bra.s    cpy3
  178. cpypgm:    move.b    (A0)+,(A3)+
  179. cpy3:    dbf    D0,cpypgm
  180.     clr.b    (A3)            ;don't forget trailing null on name
  181.  
  182. *------ First we want to put it into our seglist
  183.     lea    segexit-copybeg(A1),A2
  184.     move.l    A2,XCEXIT+2(A4)        ;patch the jump instruction
  185.     lea    start-4(PC),A2
  186.    
  187. *    Now we have:    A1 to our new fake segment
  188. *            A2 to the start of the real seglist
  189.     move.l    #(copyend-copybeg)/4,(A1)+
  190.     move.l    A1,D3
  191.     lsr.l    #2,D3            ;convert it to a bptr to the list
  192.     move.l    (A2),(A1)+        ;save our next segment pointer
  193.     clr.l    (A2)            ;and kill it from the chain
  194. *------ We have the seglist
  195.  
  196.     lea    AutoLoader(PC),A2
  197.     move.l    #(copyend-AutoLoader)-1,D0
  198. copyit    move.b    (A2)+,(A1)+
  199.     dbf    d0,copyit
  200.  
  201. *------    See if they want to do some I/O
  202.     tst.l    _BackGroundIO(A4)
  203.     beq    noio
  204.         lea     current_window(A4),A0
  205.         move.l  A0,D1
  206.     move.l    #1005,D2
  207.     move.l    DOSBase(A4),A6
  208.     callsys    Open
  209.     move.l    d0,_Backstdout(A4)
  210. noio:
  211.     move.l    AbsExecBase.w,A6
  212.  
  213. *------ If under 2.0 Flush cache
  214.    
  215.    moveq    #24,d0
  216.    cmp.w    $14(a6),d0
  217.    bcs.b    nocache
  218.    moveq    #-1,d0
  219.    callsys  CacheClearU
  220.  
  221. nocache:   
  222.     callsys    Forbid
  223.  
  224. *------ Attach the task to do the dirty work
  225.     move.l    _procname(A4),D1    ; Name of task to start
  226.     move.l    _priority(A4),D2    ; Priority of background task
  227.     move.l    _stack(A4),D4        ; Stack size of created task
  228.  
  229.     move.l    DOSBase(A4),A6
  230.     callsys    CreateProc
  231.     move.l    A6,A3        ; restore dosbase to close it
  232.     tst.l    D0
  233.     bne    ok
  234.  
  235. *------ Serious problems.  For some reason the CreateProc failed.
  236. *------ We need to free the AlocEntry memory and go home
  237.     move.l    (A7)+,A2
  238.     movea.l    ML_SIZE+ME_ADDR(A2),A1    ;locate our allocated block
  239. *------ Also must get rid of current directory
  240.         move.l  curdir(A4),D1
  241.         callsys UnLock
  242.  
  243.         move.l  A2,A0
  244.     move.l    AbsExecBase.w,A6
  245.     callsys    FreeEntry
  246.     move.l    #104,D0
  247.     bra    cliexit
  248.  
  249. ok:
  250. *------ The task started ok, attach the memory we allocated to
  251. *------    its task control block
  252.     move.l    D0,A2
  253.  
  254.     move.l    (a7)+,A1        ;locate the memory we allocated
  255.     lea    -pr_MsgPort(A2),A2
  256.     lea    TC_MEMENTRY(A2),A0
  257.  
  258.  
  259. *    ADDTAIL
  260.     LEA    LH_TAIL(A0),A0
  261.     MOVE.L    LN_PRED(A0),D0
  262.     MOVE.L    A1,LN_PRED(A0)
  263.     MOVE.L    A0,(A1)
  264.     MOVE.L    D0,LN_PRED(A1)
  265.     MOVE.L    D0,A0
  266.     MOVE.L    A1,(A0)
  267.  
  268.     move.l    #0,D0
  269.  
  270. cliexit:
  271.     move.l    AbsExecBase.w,A6
  272.     callsys    Permit
  273.     move.l    A3,A1
  274.     move.l    AbsExecBase.w,A6
  275.     callsys    CloseLibrary
  276.     movem.l    (a7)+,d1-d6/a0-a6
  277.     rts
  278.  
  279. *=======================================================================
  280. *====== Workbench Startup Code =========================================
  281. *=======================================================================
  282.  
  283. fromWorkbench:
  284.  
  285.     move.l    TC_SPLOWER(A3),_base(A4)    ; set base of stack
  286.         add.l   #128,_base(A4)          ;allow for parms overflow
  287. *------ open the DOS library:
  288.     bsr.w    openDOS
  289.  
  290.     lea    xcexit(PC),A2
  291.     move.l    A2,XCEXIT+2(A4)        ;patch the jump instruction
  292.     
  293. *------ we are now set up.  wait for a message from our starter
  294.     bsr.w    waitmsg
  295.     move.l    d0,WBenchMsg(A4)
  296.     move.l    d0,-(SP)
  297. *
  298.     move.l    d0,a2            ; get first argument
  299.     move.l    sm_ArgList(a2),d0
  300.     beq.s    do_cons
  301.     move.l    DOSBase(A4),a6
  302.     move.l    d0,a0
  303.     move.l    wa_Lock(a0),d1
  304.         callsys DupLock
  305.     move.l    d0,curdir(A4)
  306.     move.l    d0,d1
  307.     callsys    CurrentDir
  308. do_cons:
  309.     move.l    sm_ToolWindow(a2),d1    ; get the window argument
  310.     beq.s    do_main
  311.     move.l    #MODE_OLDFILE,d2
  312.     callsys    Open
  313.     move.l    d0,stdin(A4)
  314.     beq.s    do_main
  315.     lsl.l    #2,d0
  316.     move.l    d0,a0
  317.     move.l    fh_Type(a0),pr_ConsoleTask(A3)
  318. do_main:
  319.     move.l    WBenchMsg(A4),a0        ; get address of workbench message
  320.     move.l    a0,-(a7)        ; push argv
  321.     pea    NULL(A4)        ; push argc
  322.     move.l    sm_ArgList(a0),a0    ; get address of arguments
  323.     move.l    wa_Name(a0),_ProgramName(A4)    ; get name of program
  324. *------ For startup from workbench, there is no reason to go through
  325. *------ The fancy stuff to make the startup work.  Just run the
  326. *------ Code directly
  327.     jsr    __fpinit(PC)
  328.     jsr    _main
  329.     moveq.l    #0,d0
  330.     bra.w    exit2
  331.     
  332.  
  333. ************************************************************************
  334. ************************************************************************
  335. *************                                              *************
  336. ************* Start of code that is copied to fake segment *************
  337. *************                                              *************
  338. ************************************************************************
  339. ************************************************************************
  340.  
  341. copybeg:
  342.     DC.L    (copyend-copybeg)/4
  343. next:    DC.L    0
  344. AutoLoader:
  345.     move.l    a7,d0
  346.     movem.l    d1-d6/a0-a6,-(a7)
  347.     move.l    d0,a5
  348.     move.l    AbsExecBase.w,a6
  349.     lea    LinkerDB,A4        ; load base register
  350.     move.l    a7,_StackPtr(A4)
  351.  
  352.     bsr.w    openDOS
  353.     suba.l    a1,a1
  354.  
  355.     suba.l    a1,a1
  356.     callsys    FindTask
  357.     move.l    d0,A3
  358.  
  359.     move.l    TC_SPLOWER(A3),_base(A4)    ; set base of stack
  360.         add.l   #128,_base(A4)          ;allow for parms overflow
  361.  
  362.     move.l    pr_SegList(A3),a0    ;locate the segment list
  363.     add.l    A0,A0
  364.     add.l    A0,A0            ;and convert to an APTR
  365.     move.l    12(A0),A1        ;so we can access the segments
  366.     add.l    A1,A1
  367.     add.l    A1,A1
  368.  
  369.     move.l    (A1),seglist(A4)    ;save the remainder for later
  370.     move.l    (A1),12(A0)        ;cut off our segment
  371.  
  372.         move.l  curdir(A4),D1
  373.     move.l    DOSBase(A4),a6
  374.         callsys CurrentDir
  375.  
  376.     pea    commandbuf(PC)
  377.         jsr     __fpinit
  378.     jsr    _main                ; call C entrypoint
  379.     addq    #4,A7
  380.  
  381.  
  382. *------ Unlock the directory we set up for them
  383. segexit:
  384.     move.l    DOSBase(A4),a6
  385.         move.l  curdir(A4),D1
  386.         callsys UnLock
  387.  
  388.     moveq.l    #0,d0            ; set successful status
  389. xcexit:
  390. exit2:
  391.     IFEQ    TINY
  392.     move.l    _ONEXIT(A4),d0        ; exit trap function?
  393.     beq.s    exit3
  394.     move.l    d0,a0
  395.     jsr    (a0)
  396.     ENDC
  397.  
  398. exit3    jsr    MemCleanup        ; cleanup leftover memory alloc.
  399.  
  400.     jsr    __fpterm
  401.  
  402. done_1c:
  403. *------ if we ran from CLI, skip workbench cleanup:
  404.     tst.l    WBenchMsg(A4)
  405.     beq.s    exitToDOS
  406.     move.l    DOSBase(A4),a6
  407.     move.l    stdin(A4),d1
  408.     beq.s    done_4
  409.     callsys    Close
  410. done_4:
  411.  
  412. *------ return the startup message to our parent
  413. *    we forbid so workbench can't UnLoadSeg() us
  414. *    before we are done:
  415.         move.l  curdir(a4),d1
  416.         beq.s   done_5
  417.         callsys UnLock
  418.  
  419. done_5:
  420.     move.l    AbsExecBase.w,A6
  421.     callsys    Forbid
  422.     move.l    WBenchMsg(A4),a1
  423.     callsys    ReplyMsg
  424.  
  425. *------ this rts sends us back to DOS:
  426. exitToDOS:
  427.         movea.l _StackPtr(a4),a3        ; Put old stack pointer somewhere safe.
  428.  
  429. *------    They are done so unload them
  430.     move.l    seglist(A4),D1
  431.     move.l    DOSBase(A4),a6
  432.     callsys    UnLoadSeg
  433.  
  434.         move.l  a6,a1
  435.     move.l    AbsExecBase.w,a6
  436.     callsys    CloseLibrary        ; close Dos library
  437.  
  438.  
  439.     movea.l  a3,SP            ; restore stack ptr
  440.     movem.l    (a7)+,d1-d6/a0-a6
  441.     rts
  442.  
  443. *-----------------------------------------------------------------------
  444. *  Open the DOS library:
  445.  
  446. openDOS
  447.         lea    DOSName(A4),A1
  448.         moveq.l    #0,D0
  449.         callsys    OpenLibrary
  450.         move.l    D0,DOSBase(A4)
  451.         beq    noDOS
  452.         rts
  453. *-----------------------------------------------------------------------
  454. noDOS:
  455.         moveq.l    #100,d0
  456.         bra    exit2
  457.  
  458. copyend:
  459. commandbuf:
  460.  
  461. ************************************************************************
  462. ************************************************************************
  463. **************                                            **************
  464. ************** End of code that is copied to fake segment **************
  465. **************                                            **************
  466. ************************************************************************
  467. ************************************************************************
  468.  
  469. *-----------------------------------------------------------------------
  470. * This routine gets the message that workbench will send to us
  471. * called with task id in A3
  472.  
  473. waitmsg:
  474.         lea    pr_MsgPort(A3),a0      ; our process base
  475.         callsys    WaitPort
  476.         lea    pr_MsgPort(A3),a0      ; our process base
  477.         callsys    GetMsg
  478.         rts
  479.  
  480.     csect    __MERGED,1,0,0,4
  481.  
  482. *------    These externals control the task that is started
  483.     xref    _BackGroundIO        ; flag to indicate background task
  484. *                    ; wants to do I/O
  485.     xref    _stack            ; stack space for created task
  486.     xref    _procname        ; name of process to be created
  487.     xref    _priority        ; priority to create process at
  488.  
  489.     xref    DOSBase
  490.     xref    MathBase
  491.     xref    MathTransBase
  492. *
  493.     xdef    NULL,SysBase,WBenchMsg
  494.     xdef    curdir,_mbase,_mnext,_msize,_tsize
  495.     xdef    _oserr,_OSERR,_FPERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
  496.     xdef    _SIGINT,_Backstdout
  497.     xdef    _ProgramName,_StackPtr,_base
  498. *
  499. *        cnop    0,4
  500. memlist    ds.b    LN_SIZE
  501.         dc.w    1
  502.         dc.l    MEMF_PUBLIC
  503. memsize    dc.l    copyend-copybeg
  504.  
  505. XCEXIT    
  506. @XCEXIT        dc.w    $4ef9
  507.         dc.l    0
  508. seglist        dc.l    0
  509. NULL        dc.l    0        ;
  510. _base        dc.l    0        ; base of stack
  511. _mbase        dc.l    0        ; base of memory pool
  512. _mnext        dc.l    0        ; next available memory location
  513. _msize        dc.l    0        ; size of memory pool
  514. _tsize        dc.l    0        ; total size?
  515. _oserr        equ    *
  516. _OSERR        dc.l    0
  517. _FPERR        dc.l    0
  518. _SIGFPE        dc.l    0
  519. _SIGINT        dc.l    0
  520. _ONERR        dc.l    0
  521. _ONEXIT        dc.l    0
  522. _ONBREAK    dc.l    0
  523. curdir        dc.l    0
  524. SysBase        dc.l    0
  525. WBenchMsg    dc.l    0
  526. _StackPtr    dc.l    0
  527. dosCmdLen    dc.l    0
  528. dosCmdBuf    dc.l    0
  529. stdin        dc.l    0
  530. _Backstdout    dc.l    0        ;filehandle for I/O
  531. _ProgramName    dc.l    0
  532. DOSName     dc.b    'dos.library',0
  533. current_window    dc.b    '*',0
  534.         END
  535.